#endif
continue_boot_cpu:
- add $__PAGE_OFFSET,%ebx
- push %ebx /* Multiboot info struct */
- push %eax /* Multiboot magic value */
+ add $__PAGE_OFFSET,%ebx
+ push %ebx /* Multiboot info struct */
+ push %eax /* Multiboot magic value */
/* Initialize BSS (no nasty surprises!) */
mov $__bss_start-__PAGE_OFFSET,%edi
xor %eax,%eax
rep stosb
+ /* Copy all modules (dom0 + initrd if presetn) to safety, above 48MB */
+ mov (%esp),%eax
+ cmp $0x2BADB002,%eax
+ jne 2f /* skip if magic no good */
+
+ sub $__PAGE_OFFSET,%ebx /* turn back into a physaddr */
+
+ mov 0x14(%ebx),%edi /* mbi->mods_count */
+ dec %edi /* count-- */
+
+ jb 2f /* if num modules was zero !!! */
+
+ mov 0x18(%ebx),%eax /* mbi->mods_addr */
+
+ mov (%eax),%ebx /* mod[0]->mod_start */
+
+ shl $4,%edi /* count*16 */
+ add %edi,%eax
+
+ mov 0x4(%eax),%eax /* mod[mod_count-1]->end */
+
+ mov %eax,%ecx
+ sub %ebx,%ecx /* length in byte */
+
+ mov $(MAX_DIRECTMAP_ADDRESS), %edi
+ add %ecx, %edi /* src + length */
+
+ shr $2,%ecx /* ecx is length/4 */
+
+1:
+ sub $4,%eax /* eax = src, edi = dst */
+ sub $4,%edi
+ mov (%eax),%ebx
+ mov %ebx,(%edi)
+ loop 1b
+
+2:
+
/* Initialize low and high mappings of all memory with 4MB pages */
mov $idle0_pg_table-__PAGE_OFFSET,%edi
mov $0x1e3,%eax /* PRESENT+RW+A+D+4MB+GLOBAL */
* userspace dom0 and final setup is being done by final_setup_guestos.
*/
int setup_guestos(struct task_struct *p, dom0_newdomain_t *params,
- char *data_start, unsigned long data_len, char *cmdline)
+ char *phy_data_start, unsigned long data_len,
+ char *cmdline, unsigned long initrd_len)
{
struct list_head *list_ent;
- char *src, *dst;
+ char *src, *vsrc, *dst, *data_start;
int i, dom = p->domain;
unsigned long phys_l1tab, phys_l2tab;
unsigned long cur_address, alloc_address;
/* Sanity! */
if ( p->domain != 0 ) BUG();
+ /* This is all a bit grim. We've moved the modules to the "safe"
+ physical memory region above MAP_DIRECTMAP_ADDRESS (48MB). Later
+ in this routeine, we're going to copy it down into the region
+ that's actually been allocated to domain 0. This is highly likely
+ to be overlapping, so we use a forward copy.
+
+ MAP_DIRECTMAP_ADDRESS should be safe. The worst case is a machine
+ with 4GB and lots of network/disk cards that allocate loads of
+ buffers. We'll have to revist this if we ever support PAE (64GB).
+
+ */
+
+
+ data_start = map_domain_mem( (unsigned long) phy_data_start );
+
if ( strncmp(data_start, "XenoGues", 8) )
{
printk("DOM%d: Invalid guest OS image\n", dom);
__cli();
__write_cr3_counted(pagetable_val(p->mm.pagetable));
- /* Copy the guest OS image. */
- src = (char *)(data_start + 12);
+ /* Copy the guest OS image. */
+ src = (char *)(phy_data_start + 12);
+ vsrc= (char *)(data_start + 12); /* data_start invalid after first page*/
dst = (char *)virt_load_address;
- while ( src < (data_start+data_len) ) *dst++ = *src++;
+ while ( src < (phy_data_start+data_len) )
+ {
+ *dst++ = *vsrc++;
+ src++;
+
+ if ( (((unsigned long)src) & (PAGE_SIZE-1)) == 0 )
+ {
+ unmap_domain_mem( vsrc-1 );
+ vsrc = map_domain_mem( (unsigned long)src );
+ }
+ }
+ unmap_domain_mem( vsrc );
+
+ printk("copy done\n");
/* Set up start info area. */
memset(virt_startinfo_address, 0, sizeof(*virt_startinfo_address));
virt_startinfo_address->pt_base = virt_load_address +
((p->tot_pages - 1) << PAGE_SHIFT);
+ if ( initrd_len )
+ {
+ virt_startinfo_address->mod_start = (unsigned long)dst-initrd_len;
+ virt_startinfo_address->mod_len = initrd_len;
+
+ printk("Initrd len 0x%x, start at 0x%08x\n",
+ virt_startinfo_address->mod_len, virt_startinfo_address->mod_start);
+ }
+
/* Add virtual network interfaces and point to them in startinfo. */
while (params->num_vifs-- > 0) {
net_vif = create_net_vif(dom);
printk("Initialised all memory on a %luMB machine\n",
max_page >> (20-PAGE_SHIFT));
- init_page_allocator(mod[0].mod_end, MAX_MONITOR_ADDRESS);
+ init_page_allocator(__pa(&_end), MAX_MONITOR_ADDRESS);
/* These things will get done by do_newdomain() for all other tasks. */
current->shared_info = (void *)get_free_page(GFP_KERNEL);
new_dom = do_newdomain(0, 0);
if ( new_dom == NULL ) panic("Error creating domain 0\n");
+
+ /* We're going to setup domain0 using the module(s) that we
+ stashed safely above our MAX_DIRECTMAP_ADDRESS in boot/Boot.S
+
+ The second module, if present, is an initrd ramdisk
+ */
+
if ( setup_guestos(new_dom,
&dom0_params,
- __va(mod[0].mod_start),
- mod[0].mod_end - mod[0].mod_start,
- __va(mod[0].string))
+ MAX_DIRECTMAP_ADDRESS,
+ mod[mbi->mods_count-1].mod_end - mod[0].mod_start, __va(mod[0].string),
+ (mbi->mods_count==2)?
+ (mod[1].mod_end - mod[1].mod_start):0)
!= 0 ) panic("Could not set up DOM0 guest OS\n");
- release_bytes_to_allocator(__pa(&_end), mod[0].mod_end);
-
update_dom_time(new_dom->shared_info);
wake_up(new_dom);
extern struct task_struct *do_newdomain(unsigned int dom_id, unsigned int cpu);
extern int setup_guestos(
struct task_struct *p, dom0_newdomain_t *params,
- char *data_start, unsigned long data_len, char *cmdline);
+ char *data_start, unsigned long data_len,
+ char *cmdline, unsigned long initrd_len);
extern int final_setup_guestos(struct task_struct *p, dom_meminfo_t *);
struct task_struct *find_domain_by_id(unsigned int dom);